package com.lds.register.center.server.scheduled;

import com.lds.management.center.common.util.ScheduledUtil;
import com.lds.register.center.server.business.appinstance.entity.AppInstance;
import com.lds.register.center.server.business.appinstance.mapper.AppInstanceMapper;
import com.lds.register.center.server.business.appinstance.service.AppInstanceRemoteService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.Objects;

@Slf4j
@Component
@RequiredArgsConstructor
public class HeartbeatScheduled implements ApplicationRunner {
    private final AppInstanceRemoteService appInstanceRemoteService;
    private final AppInstanceMapper appInstanceMapper;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        ScheduledUtil.scheduled(10, this::execute);
    }

    private void execute() {
        final Map<Long, Long> heartbeatMap = appInstanceRemoteService.getHeartbeatMap();
        heartbeatMap.forEach((appInstanceId, lastHeartbeatTimeMillis) -> {
            boolean healthy = healthy(lastHeartbeatTimeMillis);
            updateHealthy(appInstanceId, healthy);
        });
    }

    private boolean healthy(Long lastHeartbeatTimeMillis) {
        return System.currentTimeMillis() - lastHeartbeatTimeMillis <= 15000;
    }

    /**
     * 更新健康状态
     */
    private void updateHealthy(Long appInstanceId, boolean healthy) {
        AppInstance appInstance = appInstanceMapper.selectById(appInstanceId);
        if (Objects.isNull(appInstance)) {
            appInstanceRemoteService.getHeartbeatMap().remove(appInstanceId);
            return;
        }

        if (appInstance.getHealthy() !=  healthy) {
            appInstanceMapper.updateById(
                    AppInstance.builder()
                            .id(appInstance.getId())
                            .healthy(healthy)
                            .updateTime(LocalDateTime.now())
                            .build());
            log.info("更新健康状态: appInstanceId={}, healthy={}", appInstanceId, healthy ? "已上线" : "已下线");
        }
    }
}
